package com.example.exam.controller;

import com.example.exam.constant.DocumentConstant;
import com.example.exam.constant.LoginConstant;
import com.example.exam.constant.TimeConstant;
import com.example.exam.pojo.QuestionBank;
import com.example.exam.pojo.User;
import com.example.exam.service.PictureService;
import com.example.exam.service.QuestionBankService;
import com.example.exam.service.RedisService;
import com.example.exam.service.UserService;
import com.example.exam.utils.R;
import lombok.RequiredArgsConstructor;
import org.apache.poi.POIXMLTextExtractor;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.model.PicturesTable;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author
 * @date 2023/05/27
 *
 * 考试管理
 */
@RequestMapping("/management")
@RestController
@RequiredArgsConstructor
public class ExamController {

    private final UserService userService;
    private final PictureService pictureService;
    private final QuestionBankService questionBankService;

    private final RedisService redis;

    /**
     * 学生机器宕机处理
     */
    @PostMapping("/restore")
    public Object restore (String sid) {
        //判断用户是否存在
        User user = userService.searchAllBySid(sid);
        if(user == null) {
            return R.fail("用户不存在");
        }
        String str = user.getSid() + ":" + user.getRecentlyTime();
        System.out.println(str);
        //生成token
        String token = Base64.getEncoder().encodeToString(str.getBytes());
        //将令牌删除，使其失效
        redis.del(LoginConstant.TOKEN_PREFIX + token);
        //开放重新登录
        userService.updateLanguageBySid(sid);
        return R.ok(token);
    }

    /**
     * 获取考试时间
     */
    @GetMapping("/getExamTime")
    public Object getExamTime() {
        //时间格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:SS");
        //开始时间
        Object startObj = redis.getObject(TimeConstant.START_TIME);
        //结束时间
        Object endObj = redis.getObject(TimeConstant.END_TIME);
        Map<String, Object> map = new HashMap<>(2);
        //解析起始时间
        if(startObj != null) {
            long startTime = (long) startObj;
            String startSrt = simpleDateFormat.format(new Date(startTime));
            map.put("start", startSrt);
        }else {
            map.put("start", "无限制");
        }
        //解析终止时间
        if(endObj != null) {
            long endTime = (long) endObj;
            String endSrt = simpleDateFormat.format(new Date(endTime));
            map.put("end", endSrt);
        }else {
            map.put("end", "无限制");
        }
        return R.ok(map);
    }

    /**
     * 修改考试时间,还没修改好
     */
    @PostMapping("/setExamTime")
    public Object setExamTime(String startTime, String endTime) {
        if(startTime == null || endTime == null) {
            return R.fail("开始时间或结束时间不能为空");
        }
        long startTimes = Long.parseLong(startTime);
        long endTimes = Long.parseLong(endTime);
        if(startTimes >= endTimes) {
            return R.fail("开始时间不能大于结束时间");
        }
        redis.setObject(TimeConstant.START_TIME, startTimes);
        redis.setObject(TimeConstant.END_TIME, endTimes);
        return R.ok();
    }

    /**
     *  登记题目
     */
    @PostMapping("/topic")
    public Object topic(@RequestBody QuestionBank questionBank) {
        QuestionBank questionBank1 = questionBankService.searchQuestionBank(questionBank.getTid());
        //判断是否存在题号相同的题目
        if(questionBank1 != null) {
            //存在题号相同的题目就是更新
            questionBankService.updateTopicByTid(questionBank);
        }else {
            //不存在题号相同的题目就是添加
            questionBankService.insert(questionBank);
        }
        return R.ok();
    }

    /**
     * 通过word文档批量登记题目
     */
    @PostMapping("/topicBatch")
    public Object topicBatch(MultipartFile file) {
        String text = null;
        List<String> pictureNameList = new ArrayList<>();
        HWPFDocument doc = null;
        XWPFDocument docx = null;
        POIXMLTextExtractor extractor = null;
        try {
            if(file.getOriginalFilename() != null && file.getOriginalFilename().endsWith(DocumentConstant.SUFFIX_DOC)) {
                doc = new HWPFDocument(file.getInputStream());
                //读取文档中的文字
                text = doc.getDocumentText();
                //读取文档中的图片
                PicturesTable picturesTable = doc.getPicturesTable();
                List<Picture> pictures = picturesTable.getAllPictures();
                for(Picture picture : pictures) {
                    //将图片保存进数据库
                    String pictureName = pictureService.insert(picture.suggestFileExtension(), picture.getRawContent());
                    pictureNameList.add(pictureName);
                }
            }else if(file.getOriginalFilename() != null && file.getOriginalFilename().endsWith(DocumentConstant.SUFFIX_DOCX)) {
                docx = new XWPFDocument(file.getInputStream());
                extractor = new XWPFWordExtractor(docx);
                //读取文档中的文字
                text = extractor.getText();
                //读取文档中的图片
                List<XWPFPictureData> pictureDatas = docx.getAllPictures();
                for(XWPFPictureData pictureData : pictureDatas) {
                    //将图片保存进数据库
                    String pictureName = pictureService.insert(pictureData.getFileName().split("\\.")[1], pictureData.getData());
                    pictureNameList.add(pictureName);
                }
            }else {
                return R.fail("文件格式有问题,目前只支持word文档");
            }
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (doc != null) {
                    doc.close();
                }
                if(extractor != null) {
                    extractor.close();
                }
                if(docx != null) {
                    docx.close();
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
        //切割出题目
        String[] pictureList = insertPicture(text, pictureNameList).split(DocumentConstant.PICTURE_SEPARATOR);
        //持久化进数据库
        questionBankService.batchInsert(pictureList);
        return R.ok();
    }

    /**
     * 将图片链接添加到文本
     */
    private String insertPicture(String text, List<String> pictureNameList) {
        int size = pictureNameList.size();
        int n = 0;
        String[] strs =text.split("\n");
        StringBuffer buffer = new StringBuffer();
        for(String string : strs) {
            if(n < size && "".equals(string)) {
                String str = mergeUrl(pictureNameList.get(n));
                n++;
                buffer.append(str);
            }else {
                buffer.append(string);
            }
            buffer.append("\n");
        }
        while (n < size) {
            String str = mergeUrl(pictureNameList.get(n));
            n++;
            buffer.append(str + "\n");
        }
        return buffer.toString();
    }

    /**
     * 生成图片链接
     */
    private String mergeUrl(String str) {
        //前缀
        String prefix = "<img src=\"/api/getPicture/";
        //后缀
        String suffix = "\"/>";
        return prefix + str + suffix;
    }
}
